/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package jhu.profiteer;

import jhu.profiteer.data.Character;
import jhu.profiteer.data.CharacterJpaController;
import jhu.profiteer.data.Account;
import jhu.profiteer.data.AccountJpaController;
import jhu.profiteer.data.Airplane;
import jhu.profiteer.data.AirplaneJpaController;

import jhu.profiteer.data.CurrentCommodityValue;
import jhu.profiteer.data.CurrentCommodityValueJpaController;

import jhu.profiteer.data.AirplaneCargo;
import jhu.profiteer.data.AirplaneCargoPK;
import jhu.profiteer.data.AirplaneCargoJpaController;
import jhu.profiteer.data.GameConfigurationParameters;
import jhu.profiteer.data.GameConfigurationParametersJpaController;
import jhu.profiteer.data.exceptions.NonexistentEntityException;

import java.io.IOException;
import java.util.Vector;
import java.util.ArrayList;
import javax.servlet.ServletException;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *
 * @author sclee
 */
public class TradeServlet extends HttpServlet {

    /** 
     * Processes requests for both HTTP <code>GET</code> and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");

        HttpSession session = request.getSession();
        Vector<String> notices = (Vector<String>)session.getAttribute("notices");
        if (notices == null) notices = new Vector<String>();

        Account account = null;
        Character character = null;
        Airplane airplane = null;
        String url = null;
        boolean failed = false;
        ArrayList<CurrentCommodityValue> cvlist =
                new ArrayList<CurrentCommodityValue>();

        // Search for a session attribute "character"
        character = (Character)session.getAttribute("character");
        account = (Account)session.getAttribute("account");

        // Search for a character from the database if no character in session
        if(character == null)
        {
          // Redirect to Index page if no account is found
          if(account == null) this.getServletContext()
                  .getRequestDispatcher("/index")
                  .forward(request, response);
          else
          {
            // Check if a character exists for this account
            CharacterJpaController cjc = new CharacterJpaController();
            if(cjc.testForCharacterWithAccountId(account.getId()))
              character = cjc.findCharacterByAccountId(account.getId());
            // Redirect to CharacterInformation page if no character is found
            else this.getServletContext()
                  .getRequestDispatcher("/characterInformation")
                  .forward(request, response);
          }
        }

        // Get airplane object
        // find airplane from session
        airplane = (Airplane)session.getAttribute("airplane");

        if(airplane == null)
        {
          // find airplane from database
          AirplaneJpaController ajc = new AirplaneJpaController();

          if(ajc.testForAirplaneWithCharacterId(character.getId()))
            airplane = ajc.findAirplaneByCharacterId(character.getId());
          else
          {
            if(account == null)
            {
              AccountJpaController ac = new AccountJpaController();

              if(!ac.testForAccountWithCharacterId(character.getId()))
                this.getServletContext()
                        .getRequestDispatcher("/index")
                        .forward(request, response);
              else
              {
                account = ac.findAccountByCharacterId(character.getId());
                account.setDamaged(true);
                AccountJpaController acjc = new AccountJpaController();

                try {
                    acjc.edit(account);
                } catch (NonexistentEntityException nee) {
                  notices.add("No account with that ID exists.");
                } catch (Exception e) {
                  notices.add("Error editing account.");
                }

                notices.add("This account has been damaged and needs to be " +
                        "reviewed by a game administrator.  An " +
                        "administrator will contac you once the account has" +
                        "been examined and a solution has been implemented.");
                session.setAttribute("notices", notices);
                this.getServletContext()
                        .getRequestDispatcher("/logout")
                        .forward(request, response);
              }
            }
          }
        }

        String submit = request.getParameter("submit");
        Long total_money = 0L;
        Long total_cargo = 0L;

        if(submit.equals("Purchase Fuel"))
        {
          String fuelStr = request.getParameter("fuel");
          Long fuel = 0L;

          if((fuelStr != null) && !fuelStr.isEmpty())
          {
            fuel = Long.valueOf(fuelStr);

            if(fuel <= 0)
            {
              notices.add("You entered an invalid amount of fuel to " +
                      "purchase.  Please check the amount and try again.");
              url = "/airplaneInformation";
            }
            else
            {
              // Add the value of fuel to the value of currentFuel field in Airplane.
              Long currentFuel = airplane.getCurrentFuel();

              if(currentFuel + fuel > airplane.getMaxFuel())
              {
                notices.add("You can not store that amount of fuel in the " +
                        "plane.  Please purchase a smaller amount of fuel");
                url = "/airplaneInformation";
              }
              else
              {
                // Search Game Configuration Paamtetrer
                GameConfigurationParameters gcp = null;
                GameConfigurationParametersJpaController gcpc =
                        new GameConfigurationParametersJpaController();
                gcp = gcpc.findGameConfigurationParameters();

                if(null == gcp)
                {
                  notices.add("The game has not been set up yet. Please " +
                          "contact the administrators to set up the game");
                  url = "/index";
                }
                else
                {

                  Long fuelCost = gcp.getFuelCost();

                  if(character.getMoney() < (fuelCost * fuel))
                  {
                    notices.add("You do not have enough money to purchase " +
                            "that much fuel.  Please purchase a smaller " +
                            "amount of fuel.");
                    url = "/airplaneInformation";
                  }
                  else
                  {
                    airplane.setCurrentFuel(airplane.getCurrentFuel() + fuel);
                    character.setMoney(character.getMoney() -
                            (fuel * fuelCost));
                    AirplaneJpaController ajc = new AirplaneJpaController();
                    CharacterJpaController cjc = new CharacterJpaController();

                    try
                    {
                      url = "/airplaneInformation";
                      ajc.edit(airplane);
                      cjc.edit(character);
                      notices.add("You have successfully purchased fuel.");
                    } catch (NonexistentEntityException nee) {
                        notices.add("No airplane/character exists in database.");
                    } catch (Exception e) {
                        notices.add("Error editing information in database.");
                    }
                  }
                }
              }
            }
          }
          else
          {
            if(null == notices) notices = new Vector<String>();
            notices.add("You must supply a quatity of fuel to purchase.");
          }

          // Set session attributes
          session.setAttribute("account",account);
          session.setAttribute("character",character);
          session.setAttribute("airplane",airplane);
          session.setAttribute("notices",notices);
          // Forward the request to the url
          getServletContext()
                  .getRequestDispatcher(url)
                  .forward(request, response);
        }
        else
        {

                  System.out.println("Buy/Sell Entered");
                  //search database for all current CommmodityValue objects
                  CurrentCommodityValueJpaController ccvc = new CurrentCommodityValueJpaController();
                  cvlist = (ArrayList<CurrentCommodityValue>) ccvc.findCurrentCommodityValuesByCharacterId(character.getId());

                  //AirplaneCargoJpaController acc = new AirplaneCargoJpaController();



                  for (int i = 0; i < cvlist.size(); i++) {
                      CurrentCommodityValue ccv = (CurrentCommodityValue) cvlist.get(i);

                      String quantityStr = request.getParameter(ccv.getId().getCommodityId().toString());
                      String commodity = (String)session.getAttribute(ccv.getId().getCommodityId().toString());
                      Long quantity = new Long(0);
                      if (commodity == null) commodity = "";

                      if (!quantityStr.equals(""))
                          quantity = Long.valueOf(quantityStr);
                      else
                          quantity = null;

                      if (quantity != null) {
                          if (quantity == null || quantity < 0) {
                              //conversion fails or less than zero
                              notices.add("You have entered an invalid quantity value. Please check your numbers and try again.");
                              failed = true;
                          } else if (quantity > 0) {
                              total_money += ccv.getPrice() * quantity;
                              //AirplaneCargo ac = acc.findAirplaneCargo(airplane.getId(), ccv.getCommodityId());
                              total_cargo += quantity;
                          }

                          if (submit.equals("Buy")) {
                              if (character.getMoney() < total_money) {
                                  notices.add("You failed to buy "+ quantity + " " + commodity);
                                  notices.add("You do not have enough money to make that purchase.");
                                  failed = true;
                                  url = "/market";
                              } else if (airplane.getCurrentCargoCapacity() + total_cargo > airplane.getMaxCargoCapacity()) {
                                  notices.add("You failed to buy "+ quantity + " " + commodity);
                                  notices.add("You do not have enough space on your airplane to make that purchase");
                                  failed = true;
                                  url = "/market";
                              } else {
                                  // calculate money
                                  AirplaneCargoJpaController acjc = new AirplaneCargoJpaController();
                                 // AirplaneCargo cargo = acjc.findAirplaneCargo(airplane.getId(), ccv.getId().getCommodityId());
                                  if (!acjc.testForAirplaneCargo(airplane.getId(), ccv.getId().getCommodityId())) {
                                      AirplaneCargo newCargo = new AirplaneCargo();
                                      AirplaneCargoPK acPK = new AirplaneCargoPK();
                                      acPK.setAirplaneId(airplane.getId());
                                      acPK.setCommodityId(ccv.getId().getCommodityId());
                                      newCargo.setId(acPK);
                                      newCargo.setQuantity(quantity);

                                      notices.add("You bought "+ quantity + " " + commodity);
                                      try {
                                          acjc.create(newCargo);
                                      } catch (NonexistentEntityException nee) {
                                          nee.printStackTrace();
                                          notices.add("Could not create a new cargo for " + ccv.getId().getCommodityId() + ".");
                                      } catch (Exception e) {
                                          e.printStackTrace();
                                          notices.add("Error editing cargo.");
                                      }

                                  } else {
                                      AirplaneCargo cargo = acjc.findAirplaneCargo(airplane.getId(), ccv.getId().getCommodityId());
                                      cargo.setQuantity(cargo.getQuantity() + quantity);
                                      notices.add("You bought "+ quantity + " " + commodity);
                                      try {
                                          acjc.edit(cargo);
                                      } catch (NonexistentEntityException nee) {
                                          nee.printStackTrace();
                                          notices.add("Could not edit a cargo info for " + ccv.getId().getCommodityId() + ".");
                                      } catch (Exception e) {
                                          e.printStackTrace();
                                          notices.add("Error editing cargo.");
                                      }
                                  }

                              }
                              //Long currentCargoCapacity = airplane.getCurrentCargoCapacity();

                          } else if (submit.equals("Sell")) {
                              // calculate money
                              AirplaneCargoJpaController acjc = new AirplaneCargoJpaController();
                              AirplaneCargo cargo = acjc.findAirplaneCargo(airplane.getId(), ccv.getId().getCommodityId());
                              if (cargo == null) {
                                  notices.add("You have attempted to sell a commodity you do not own");
                                  failed = true;
                                  url = "/market";
                                  break;
                              } else {

                                  if (cargo.getQuantity() < quantity) {
                                      notices.add("You do not have enough " + commodity + " to sell");
                                      failed = true;
                                      url = "/market";
                                      break;
                                  } else {
                                      cargo.setQuantity(cargo.getQuantity() - quantity);
                                      notices.add("You sold "+ quantity + " " + commodity);
                                      if (cargo.getQuantity() == 0) {
                                          acjc.destroy(cargo.getId().getAirplaneId(), cargo.getId().getCommodityId());
                                      } else {
                                          try {

                                              acjc.edit(cargo);
                                          } catch (NonexistentEntityException nee) {
                                              nee.printStackTrace();
                                              notices.add("Could not edit cargo information.");
                                          } catch (Exception e) {
                                              e.printStackTrace();
                                              notices.add("Error editing cargo.");
                                          }
                                      }
                                  }
                              }
                          } else {
                              notices.add("Submit parameter must be Buy/Sell/Purchase Fuel");
                              failed = true;
                              url = "/market";
                          }
                      }
                  }

            if (!failed) {
                if (submit.equals("Buy")) {
                    // update total money
                    character.setMoney(character.getMoney() - total_money);
                    notices.add("You have successfully purchased the commodities");
                } else if (submit.equals("Sell")) {

                    character.setMoney(character.getMoney() + total_money);
                    notices.add("You have successfully sold the commodities!");

                }
                url = "/market";
                CharacterJpaController cjc = new CharacterJpaController();
                try {
                    cjc.edit(character);
                } catch (NonexistentEntityException nee) {
                    nee.printStackTrace();
                    notices.add("No character with that ID exists.");
                } catch (Exception e) {
                    e.printStackTrace();
                    notices.add("Error editing character.");
                }
            }
                  
              // Set session attributes
              session.setAttribute("account",account);
              session.setAttribute("character",character);
              session.setAttribute("airplane",airplane);
              session.setAttribute("notices",notices);

              System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@url: " + url);
              // Forward the request to the url
              RequestDispatcher dispatcher = getServletContext().getRequestDispatcher(url);
              dispatcher.forward(request, response);
        }
    }

    // <editor-fold defaultstate="collapsed" desc="HttpServlet methods. Click on the + sign on the left to edit the code.">
    /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     * @return a String containing servlet description
     */
    @Override
    public String getServletInfo() {
        return "Short description";
    }// </editor-fold>
}
